package gates;

/**
 * Nand all inputs composite gate represented by elementary gates:
 * This is a representation of the inversion about the mean in terms of elementary gates. 
 * This representation can be found in <a href="http://arxiv.org/abs/quant-ph/0301079">Grover's Algorithm: Quantum Database Search</a> page 24
 * @author Jan Zaucha
 *
 */
public class NandComposite extends CompositeGate {

	/**
	 * Protected constructor to create an instance of this object
	 * 
	 * @param numQubits The number of qubits in the register
	 */
	protected NandComposite(int numQubits) {
		super(createGates(numQubits));
	}

	/** Private method to create an array of gates needed to create a composition to send to superclass */
	private static Gate[] createGates(int numQubits){
		// Test arguments and throw appropriate exception
		if (numQubits<2){
			throw new IllegalArgumentException("Too few qubits to perform operation");
		}
		Gate[] im = new Gate[2*numQubits+5]; 
		// first not gate on all qubits
		for(int i=0; i<numQubits; i++){
			im[i] = Factory.createNot(i);
		}
		// then iI on first qubit and H on last qubit
		im[numQubits] = Factory.createComplexIdentity(0);
		im[numQubits+1] = Factory.createHadamard(numQubits-1);
		im[numQubits+2] = Factory.createAllCnot(numQubits-1);
		im[numQubits+3] = Factory.createHadamard(numQubits-1);
		im[numQubits+4] = Factory.createComplexIdentity(0);
		for(int j=0; j<numQubits; j++){
			im[j+numQubits+5] = Factory.createNot(j);
		}
		return im;

	}
	
	/**
	 * Return the name of this gate.
	 */
	public String getName() {
		return "Inversion about Mean";
	}

}
